home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / MUI / CALC / CALC.C next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  24.3 KB  |  754 lines

  1. /*
  2.  * Copyright (c) 1993-1997, Silicon Graphics, Inc.
  3.  * ALL RIGHTS RESERVED 
  4.  * Permission to use, copy, modify, and distribute this software for 
  5.  * any purpose and without fee is hereby granted, provided that the above
  6.  * copyright notice appear in all copies and that both the copyright notice
  7.  * and this permission notice appear in supporting documentation, and that 
  8.  * the name of Silicon Graphics, Inc. not be used in advertising
  9.  * or publicity pertaining to distribution of the software without specific,
  10.  * written prior permission. 
  11.  *
  12.  * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
  13.  * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
  14.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
  15.  * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
  16.  * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
  17.  * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
  18.  * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
  19.  * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
  20.  * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
  21.  * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
  22.  * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
  23.  * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
  24.  * 
  25.  * US Government Users Restricted Rights 
  26.  * Use, duplication, or disclosure by the Government is subject to
  27.  * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
  28.  * (c)(1)(ii) of the Rights in Technical Data and Computer Software
  29.  * clause at DFARS 252.227-7013 and/or in similar or successor
  30.  * clauses in the FAR or the DOD or NASA FAR Supplement.
  31.  * Unpublished-- rights reserved under the copyright laws of the
  32.  * United States.  Contractor/manufacturer is Silicon Graphics,
  33.  * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
  34.  *
  35.  * OpenGL(R) is a registered trademark of Silicon Graphics, Inc.
  36.  */
  37.  
  38. /******************************************************************************
  39.  *                                                                            *
  40.  *                Reverse-Polish-Notation (RPN) calculator                    *
  41.  *                                                                            *
  42.  *                Written by Tom Davis 1991                                   *
  43.  *          Converted to OpenGL/GLUT:  Tom Davis 1997              *
  44.  *                                                                            *
  45.  *                                                                            *
  46.  * Calc is a Reverse-Polish-Notation (RPN) calculator.  You must enter the    *
  47.  * operands first, then the operation.  For example, to add 3 and 4, press    *
  48.  * [3] [Enter] [4] [+].  If the operation is unary, like sine, it operates    *
  49.  * on the bottom element of the display. To take the sine of .54, do:         *
  50.  *                                                                            *
  51.  * [.] [5] [4] [Sin].                                                         *
  52.  *                                                                            *
  53.  * The last 6 entries of the stack are visible, and you can scroll to see the *
  54.  * rest.  All operations are performed on the element(s) at the bottom of the *
  55.  * stack.  The bottom element is called 'x' and the next element up is called *
  56.  * 'y'.                                                                       *
  57.  *                                                                            *
  58.  * The [+/-] key changes the sign of x.  To find the cosine of -.22, do:      *
  59.  *                                                                            *
  60.  * [.] [2] [2] [+/-] [Cos].                                                   *
  61.  *                                                                            *
  62.  * The [Inv] key changes the operation of some of the other keys so they      *
  63.  * perform the inverse operation.  It is only active for one keystroke.       *
  64.  * Press [Inv] again to cancel the operation.                                 *
  65.  *                                                                            *
  66.  * [Sto] and [Rcl] stores and recalls a single value.                         *
  67.  *                                                                            *
  68.  * [Dup2] duplicates the bottom 2 items on the stack.                         *
  69.  *                                                                            *
  70.  * [Roll] rolls all the stack elements down one, and puts the bottom element  *
  71.  * on the top.                                                                *
  72.  *                                                                            *
  73.  * [Exch] swaps the bottom two elements.                                      *
  74.  *                                                                            *
  75.  * [Int] gives the integer part.                                              *
  76.  *                                                                            *
  77.  * [Inv] [Frac] gives the fractional part.                                    *
  78.  *                                                                            *
  79.  * [Clr] clears the bottom element to zero.  Use this when you get some kind  *
  80.  * of error.                                                                  *
  81.  *                                                                            *
  82.  * [B10] and [B16] put you in base 10 or base 16 mode.  Numbers with          *
  83.  * fractional parts are always displayed in base 10.  In base 16 mode, the    *
  84.  * keys [a] through [f] are used for numeric entry.  They do nothing,         *
  85.  * otherwise.                                                                 *
  86.  *                                                                            *
  87.  * [And], [Or] and [Not] are logical operations on 32 bit integers.  If       *
  88.  * there's a fractional part, they don't do anything.                         *
  89.  *                                                                            *
  90.  * To remember a sequence of keystrokes, press [Prog], then the sequence of   *
  91.  * keystrokes, and then [Prog] again.  For example, if you want to            *
  92.  * calculate x^2 + y^2 repeatedly, where x and y are the two bottom entries   *
  93.  * of the stack, do this:                                                     *
  94.  *                                                                            *
  95.  * [Prog] [Inv] [x^2] [Exch] [Inv] [x^2] [+] [Prog].                          *
  96.  *                                                                            *
  97.  * Then, to calculate 5^2+7^2, do this:                                       *
  98.  *                                                                            *
  99.  * [5] [Enter] [7] [Run].                                                     *
  100.  *                                                                            *
  101.  * The following keys from the computer keyboard are understood by calc:      *
  102.  *                                                                            *
  103.  * [0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [.], [Enter],            *
  104.  * [+], [-], [*], [/], [a], [b], [c], [d], [e], [f].                          *
  105.  *                                                                            *
  106.  ******************************************************************************/
  107.  
  108. #include <GL/glut.h>
  109. #include <math.h>
  110. #include <stdlib.h>
  111. #include <stdio.h>
  112. #include <string.h>
  113. #include <mui/mui.h>
  114. #include "calc.h"
  115.  
  116. /* Many systems lack the trunc routine. */
  117. #ifndef __sgi
  118. #define trunc(x) ((float)((int)x))
  119. /* Alternative trunc macro: ((x > 0.0) ? floor(x) : -floor(-x)) */
  120. #endif
  121.  
  122. #define Bwidth            44
  123. #define Bheight         25
  124. #define Bhspace         10
  125. #define Bvspace            10
  126. #define Displaylines    6
  127.  
  128. #define THUMBHEIGHT 20
  129. #define ARROWSPACE 40
  130. #define SLIDERWIDTH 20
  131.  
  132. #define Stackdepth  200
  133.  
  134. /* Some <math.h> files do not define M_PI... */
  135. #ifndef M_PI
  136. #define M_PI 3.14159265358979323846
  137. #endif
  138.  
  139. void interpclick(int);
  140. void showhelp(void);
  141.  
  142. char *CS[Stackdepth+Displaylines];
  143.  
  144. double calcdata[Stackdepth+Displaylines];
  145.  
  146. int CSP = Displaylines-1;
  147. int invmode = 0;
  148. int base = 10;
  149. float memory = 0.0;
  150. int degreemode = 1;
  151.  
  152. int savingprog = 0;
  153. int program[5000];
  154. int proglen = 0;
  155.  
  156. #define WIDTH 6
  157. #define HEIGHT 8
  158.  
  159. muiObject *tl;
  160.  
  161. struct calcbutton {
  162.     char *label, *invlabel;
  163.     muiObject *b;
  164.     int type;
  165. } keypad[HEIGHT][WIDTH];
  166.  
  167.  
  168. void butcallback(muiObject *obj, enum muiReturnValue r)
  169. {
  170.     int but = muiGetID(obj);
  171.     interpclick(but);
  172.     r = r;
  173. }
  174.  
  175. void loadcb(int row, int col, char *lab, char *invlab, int type)
  176. {
  177.     struct calcbutton *cb = &keypad[row][col];
  178.     cb->label = lab;
  179.     cb->invlabel = invlab;
  180.     cb->type = type;
  181.     cb->b = muiNewButton(Bhspace+col*(Bhspace+Bwidth), (col+1)*(Bhspace+Bwidth),
  182.                 Bvspace+row*(Bvspace+Bheight), (row+1)*(Bvspace+Bheight));
  183.     muiLoadButton(cb->b, lab);
  184.     muiSetCallback(cb->b, butcallback);
  185.     muiSetID(cb->b, type);
  186. }
  187.  
  188. void initkeypad(void)
  189. {
  190.     int xmin, xmax, ymin, ymax;
  191.  
  192.     loadcb(0, 0, "Exch", "Exch", Exchkey);
  193.     loadcb(0, 1, "0", "0", Zerokey);
  194.     loadcb(0, 2, ".", ".", Dotkey);
  195.     loadcb(0, 3, "+/-", "+/-", Flipsignkey);
  196.     loadcb(0, 4, "/", "/", Dividekey);
  197.     loadcb(0, 5, "Deg", "Deg", Radkey);
  198.     loadcb(1, 0, "Roll", "Roll", Rollkey);
  199.     loadcb(1, 1, "1", "1", Onekey);
  200.     loadcb(1, 2, "2", "2", Twokey);
  201.     loadcb(1, 3, "3", "3", Threekey);
  202.     loadcb(1, 4, "*", "*", Timeskey);
  203.     loadcb(1, 5, "Clr", "Clr", Clearkey);
  204.     loadcb(2, 0, "Dup2", "Dup2", Dup2key);
  205.     loadcb(2, 1, "4", "4", Fourkey);
  206.     loadcb(2, 2, "5", "5", Fivekey);
  207.     loadcb(2, 3, "6", "6", Sixkey);
  208.     loadcb(2, 4, "-", "-", Minuskey);
  209.     loadcb(2, 5, "And", "And", Andkey);
  210.     loadcb(3, 0, "Enter", "Enter", Enterkey);
  211.     loadcb(3, 1, "7", "7", Sevenkey);
  212.     loadcb(3, 2, "8", "8", Eightkey);
  213.     loadcb(3, 3, "9", "9", Ninekey);
  214.     loadcb(3, 4, "+", "+", Pluskey);
  215.     loadcb(3, 5, "Or", "Or", Orkey);
  216.     loadcb(4, 0, "Sin", "Asin", Sinkey);
  217.     loadcb(4, 1, "Cos", "Acos", Coskey);
  218.     loadcb(4, 2, "Tan", "Atan", Tankey);
  219.     loadcb(4, 3, "Int", "Frac", Intkey);
  220.     loadcb(4, 4, "Help", "Help", Helpkey);
  221.     loadcb(4, 5, "Not", "Not", Notkey);
  222.     loadcb(5, 0, "e^x", "Ln", Expkey);
  223.     loadcb(5, 1, "10^x", "Log", Tentoxkey);
  224.     loadcb(5, 2, "Sqrt", "x^2", Sqrtkey);
  225.     loadcb(5, 3, "y^x", "y^(1/x)", Xtoykey);
  226.     loadcb(5, 4, "Run", "Run", Runkey);
  227.     loadcb(5, 5, "B16", "B16", Base16key);
  228.     loadcb(6, 0, "Inv", "Inv", Invkey);
  229.     loadcb(6, 1, "Rcl", "Rcl", Recallkey);
  230.     loadcb(6, 2, "Sto", "Sto", Storekey);
  231.     loadcb(6, 3, "1/x", "1/x", Oneoverkey);
  232.     loadcb(6, 4, "Prog", "Prog", Progkey);
  233.     loadcb(6, 5, "B10", "B10", Base10key);
  234.     loadcb(7, 0, "a", "a", Akey);
  235.     loadcb(7, 1, "b", "b", Bkey);
  236.     loadcb(7, 2, "c", "c", Ckey);
  237.     loadcb(7, 3, "d", "d", Dkey);
  238.     loadcb(7, 4, "e", "e", Ekey);
  239.     loadcb(7, 5, "f", "f", Fkey);
  240.     tl = muiNewTextList(Bhspace, HEIGHT*Bheight + (HEIGHT+1)*Bvspace,
  241.                     WIDTH*(Bhspace+Bwidth), Displaylines);
  242.     muiGetObjectSize(tl, &xmin, &ymin, &xmax, &ymax);
  243.     muiSetTLStrings(tl, CS);
  244. }
  245.  
  246. /*
  247. void drawdisplay(void)
  248. {
  249.     settltop(cdisplay, CSP - Displaylines + 1);
  250.     cdisplay->count = CSP+1;
  251.     adjustslider(cdisplay, cdisplay->vs);
  252.     setvsarrowdelta(cdisplay->vs, 1);
  253.     drawtl(cdisplay); swapbuffers();
  254. }
  255.  
  256. void drawkeypad(void)
  257. {
  258.     int i, j;
  259.  
  260.     backgroundclear();
  261.     for (i = 0; i < HEIGHT; i++)
  262.         for (j = 0; j < WIDTH; j++)
  263.         drawbut(keypad[i][j].b);
  264.     drawdisplay();
  265. }
  266. */
  267.  
  268. void loadbuttons(int inv)
  269. {
  270.     int i, j;
  271.  
  272.     for (i = 0; i < HEIGHT; i++)
  273.         for (j = 0; j < WIDTH; j++) {
  274.         if (inv)
  275.             muiLoadButton(keypad[i][j].b, keypad[i][j].invlabel);
  276.         else
  277.             muiLoadButton(keypad[i][j].b, keypad[i][j].label);
  278.     }
  279.     glutPostRedisplay();
  280. }
  281.  
  282. void initcalc(void)
  283. {
  284.     int i;
  285.     
  286.     glutInitWindowSize(WIDTH*Bwidth+(WIDTH+1)*Bhspace,
  287.         HEIGHT*Bheight+(HEIGHT+2)*Bvspace+Displaylines*20+7);
  288.     glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE);
  289.     glutCreateWindow("RPN Calc");
  290.     muiInit();
  291.     muiNewUIList(1);
  292.     for (i = 0; i < Stackdepth+Displaylines; i++) {
  293.         CS[i] = (char *)malloc(50);
  294.     *CS[i] = ' ';
  295.     *(CS[i]+1) = 0;
  296.     }
  297.     initkeypad();
  298. }
  299.  
  300. void formatentry(int s)
  301. {
  302.     if (calcdata[s] - trunc(calcdata[s]) == 0 &&
  303.             (calcdata[s] < 1.0e9 && -1.0e9 < calcdata[s])) {
  304.     if (base == 10) {
  305.         sprintf(CS[s], "%15d", (int)calcdata[s]);
  306.     } else {
  307.         sprintf(CS[s], "0x%13x", (int)calcdata[s]);
  308.     }
  309.     } else {
  310.         if (calcdata[s] < 1.0e9 && -1.0e9 < calcdata[s] &&
  311.         (calcdata[s] > 1.0e-5 || calcdata[s] < -1.0e-5))
  312.             sprintf(CS[s], "%15.12f", calcdata[s]);
  313.     else
  314.         sprintf(CS[s], "%15.12e", calcdata[s]);
  315.     }
  316. }
  317.  
  318. /* ARGSUSED1 */
  319. void kbd(unsigned char c, int x, int y)
  320. {
  321.     switch (c) {
  322.     case 'A': case 'a': interpclick(Akey); break;
  323.     case 'B': case 'b': interpclick(Bkey); break;
  324.     case 'C': case 'c': interpclick(Ckey); break;
  325.     case 'D': case 'd': interpclick(Dkey); break;
  326.     case 'E': case 'e': interpclick(Ekey); break;
  327.     case 'F': case 'f': interpclick(Fkey); break;
  328.     case '0': interpclick(Zerokey); break;
  329.     case '1': interpclick(Onekey); break;
  330.     case '2': interpclick(Twokey); break;
  331.     case '3': interpclick(Threekey); break;
  332.     case '4': interpclick(Fourkey); break;
  333.     case '5': interpclick(Fivekey); break;
  334.     case '6': interpclick(Sixkey); break;
  335.     case '7': interpclick(Sevenkey); break;
  336.     case '8': interpclick(Eightkey); break;
  337.     case '9': interpclick(Ninekey); break;
  338.     case '.': interpclick(Dotkey); break;
  339.     case '+': interpclick(Pluskey); break;
  340.     case '-': interpclick(Minuskey); break;
  341.     case '*': interpclick(Timeskey); break;
  342.     case '/': interpclick(Dividekey); break;
  343.     case '\n': case '\r': interpclick(Enterkey); break;
  344.     }
  345.     
  346. }
  347.  
  348. void main(int argc, char **argv)
  349. {
  350.     glutInit(&argc, argv);
  351.     initcalc();
  352.     formatentry(Displaylines-1);
  353.     glutKeyboardFunc(kbd);  /* overrides mui cmd */
  354.     glutMainLoop();
  355. }
  356.  
  357. int inputptr = 0;
  358. int enablepush = 0;
  359.  
  360. void push(void)
  361. {
  362.     CSP++;
  363.     inputptr = 0;
  364.     *CS[CSP] = ' ';
  365.     *(CS[CSP]+1) = 0;
  366.     muiSetTLTopInt(tl, CSP - Displaylines + 1);
  367. }
  368.  
  369. void doenter(void)
  370. {
  371.     int isdot = 0;
  372.     
  373.     char *s = CS[CSP];
  374.     while (*s) {if (*s++ == '.') isdot=1; }
  375.     if (enablepush) {
  376.     strcpy(CS[CSP+1], CS[CSP]);
  377.     calcdata[CSP+1] = calcdata[CSP];
  378.     CSP++;
  379.     } else {
  380.         if (isdot || base == 10)
  381.         calcdata[CSP] = atof(CS[CSP]);
  382.     else
  383.         calcdata[CSP] = (double) strtol(CS[CSP], 0, 16);
  384.     enablepush = 1;
  385.     inputptr = 0;
  386.     }
  387.     formatentry(CSP);
  388.     muiSetTLTopInt(tl, CSP - Displaylines + 1);
  389.     glutPostRedisplay();
  390. }
  391.  
  392. void binop(char c)
  393. {
  394.     int i, j;
  395.  
  396.     if (enablepush == 0) doenter();
  397.     if (CSP < Displaylines) return;
  398.     switch (c) {
  399.     case '+':
  400.         calcdata[CSP-1] = calcdata[CSP-1] + calcdata[CSP];
  401.         break;
  402.     case '-':
  403.         calcdata[CSP-1] = calcdata[CSP-1] - calcdata[CSP];
  404.         break;
  405.     case '*':
  406.         calcdata[CSP-1] = calcdata[CSP-1] * calcdata[CSP];
  407.         break;
  408.     case '/':
  409.         calcdata[CSP-1] = calcdata[CSP-1] / calcdata[CSP];
  410.         break;
  411.     case '^':
  412.         if (invmode == 0)
  413.             calcdata[CSP-1] = pow(calcdata[CSP-1], calcdata[CSP]);
  414.         else
  415.             calcdata[CSP-1] = pow(calcdata[CSP-1], 1.0/calcdata[CSP]);
  416.         break;
  417.     case '&':
  418.         if (calcdata[CSP-1] - trunc(calcdata[CSP-1]) != 0) return;
  419.         if (calcdata[CSP] - trunc(calcdata[CSP]) != 0) return;
  420.         i = calcdata[CSP-1]; j = calcdata[CSP];
  421.         calcdata[CSP-1] = (int)(i&j);
  422.         break;
  423.     case '|':
  424.         if (calcdata[CSP-1] - trunc(calcdata[CSP-1]) != 0) return;
  425.         if (calcdata[CSP] - trunc(calcdata[CSP]) != 0) return;
  426.         i = calcdata[CSP-1]; j = calcdata[CSP];
  427.         calcdata[CSP-1] = (int)(i|j);
  428.         break;
  429.     }
  430.     CS[CSP][0] = 0;
  431.     CSP--;
  432.     formatentry(CSP);
  433.     muiSetTLTopInt(tl, CSP - Displaylines + 1);
  434.     glutPostRedisplay();
  435.     enablepush = 1;
  436. }
  437.  
  438. void unop(int c)
  439. {
  440.     int i;
  441.  
  442.     if (enablepush == 0) doenter();
  443.     switch (c) {
  444.         case Storekey:
  445.         memory = calcdata[CSP];
  446.         break;
  447.     case Recallkey:
  448.         doenter();
  449.         calcdata[CSP] = memory;
  450.         break;
  451.     case Flipsignkey:
  452.         calcdata[CSP] = -calcdata[CSP];
  453.         break;
  454.     case Oneoverkey:
  455.         calcdata[CSP] = 1.0/calcdata[CSP];
  456.         break;
  457.     case Clearkey:
  458.         calcdata[CSP] = 0.0;
  459.         enablepush = 0;
  460.         formatentry(CSP);
  461.         glutPostRedisplay();
  462.         return;
  463.     case Sinkey:
  464.         if (invmode) {
  465.             calcdata[CSP] = asin(calcdata[CSP]);
  466.         if (degreemode) calcdata[CSP] *= 180.0/M_PI;
  467.         } else {
  468.         if (degreemode) calcdata[CSP] *= M_PI/180.0;
  469.             calcdata[CSP] = sin(calcdata[CSP]);
  470.         }
  471.         break;
  472.     case Coskey:
  473.         if (invmode) {
  474.             calcdata[CSP] = acos(calcdata[CSP]);
  475.         if (degreemode) calcdata[CSP] *= 180.0/M_PI;
  476.         } else {
  477.         if (degreemode) calcdata[CSP] *= M_PI/180.0;
  478.             calcdata[CSP] = cos(calcdata[CSP]);
  479.         }
  480.         break;
  481.     case Tankey:
  482.         if (invmode) {
  483.             calcdata[CSP] = atan(calcdata[CSP]);
  484.         if (degreemode) calcdata[CSP] *= 180.0/M_PI;
  485.         } else {
  486.         if (degreemode) calcdata[CSP] *= M_PI/180.0;
  487.             calcdata[CSP] = tan(calcdata[CSP]);
  488.         }
  489.         break;
  490.     case Tentoxkey:
  491.         if (invmode)
  492.             calcdata[CSP] = log10(calcdata[CSP]);
  493.         else
  494.             calcdata[CSP] = pow(10, calcdata[CSP]);
  495.         break;
  496.     case Expkey:
  497.         if (invmode)
  498.             calcdata[CSP] = log(calcdata[CSP]);
  499.         else
  500.             calcdata[CSP] = exp(calcdata[CSP]);
  501.         break;
  502.     case Intkey:
  503.         if (invmode)
  504.             calcdata[CSP] = calcdata[CSP] - trunc(calcdata[CSP]);
  505.         else
  506.             calcdata[CSP] = trunc(calcdata[CSP]);
  507.         break;
  508.     case Sqrtkey:
  509.         if (invmode==0)
  510.             calcdata[CSP] = sqrt(calcdata[CSP]);
  511.         else
  512.             calcdata[CSP] = calcdata[CSP]*calcdata[CSP];
  513.         break;
  514.     case Notkey:
  515.         if (calcdata[CSP] - trunc(calcdata[CSP]) != 0) return;
  516.         i = calcdata[CSP];
  517.         calcdata[CSP] = (int)(~i);
  518.         break;
  519.     }
  520.     formatentry(CSP);
  521.     muiSetTLTopInt(tl, CSP - Displaylines + 1);
  522.     glutPostRedisplay();
  523.     enablepush = 1;
  524. }
  525.  
  526. void interpclick(int x)
  527. {
  528.     int i, rcount;
  529.     float f;
  530.     char *c;
  531.     
  532.     if (x == 0) return;
  533.     if (savingprog && x != Progkey && x != Runkey)
  534.         program[proglen++] = x;
  535.     if ((Zerokey <= x && x <= Ninekey) || x == Dotkey ||
  536.         ((base == 16) && (Akey <= x && x <= Fkey))) {
  537.         if (enablepush) push();
  538.     enablepush = 0;
  539.     if (x == Dotkey)
  540.         CS[CSP][inputptr++] = '.';
  541.     else if (Akey <= x && x <= Fkey)
  542.         CS[CSP][inputptr++] = 'a' + x - Akey;
  543.     else
  544.         CS[CSP][inputptr++] = '0'+x-Zerokey;
  545.     CS[CSP][inputptr] = 0;
  546.     muiSetTLTopInt(tl, CSP - Displaylines + 1);
  547.     glutPostRedisplay();
  548.     } else switch (x) {
  549.     case Pluskey:
  550.         binop('+'); break;
  551.     case Minuskey:
  552.         binop('-'); break;
  553.     case Timeskey:
  554.         binop('*'); break;
  555.     case Dividekey:
  556.         binop('/'); break;
  557.     case Xtoykey:
  558.         binop('^'); break;
  559.     case Helpkey:
  560.         showhelp(); break;
  561.     case Clearkey:
  562.         unop(Clearkey); break;
  563.     case Flipsignkey:
  564.         unop(Flipsignkey); break;
  565.     case Enterkey:
  566.         doenter();
  567.         break;
  568.     case Exchkey:
  569.         if (CSP < Displaylines) break;
  570.         if (enablepush == 0) doenter();
  571.         f = calcdata[CSP];
  572.         calcdata[CSP] = calcdata[CSP-1];
  573.         calcdata[CSP-1] = f;
  574.         c = CS[CSP];
  575.         CS[CSP] = CS[CSP-1];
  576.         CS[CSP-1] = c;
  577.         glutPostRedisplay();
  578.         break;
  579.     case Rollkey:
  580.         if (CSP < Displaylines) break;
  581.         rcount = CSP - Displaylines+1;
  582.         if (enablepush == 0) doenter();
  583.         f = calcdata[CSP];
  584.         c = CS[CSP];
  585.         for (i = 0; i < rcount; i++) {
  586.         calcdata[CSP-i] = calcdata[CSP-i-1];
  587.         CS[CSP-i] = CS[CSP-i-1];
  588.         }
  589.         calcdata[CSP-rcount] = f;
  590.         CS[CSP-rcount] = c;
  591.         glutPostRedisplay();
  592.         break;
  593.     case Dup2key:
  594.         if (CSP < Displaylines) break;
  595.         if (enablepush == 0) doenter();
  596.         strcpy(CS[CSP+2], CS[CSP]);
  597.         calcdata[CSP+2] = calcdata[CSP];
  598.         strcpy(CS[CSP+1], CS[CSP-1]);
  599.         calcdata[CSP+1] = calcdata[CSP-1];
  600.         CSP += 2;
  601.         muiSetTLTopInt(tl, CSP - Displaylines + 1);
  602.         glutPostRedisplay();
  603.         break;
  604.     case Radkey:
  605.         if (degreemode) {
  606.             keypad[0][5].label = "Rad";
  607.         keypad[0][5].invlabel = "Rad";
  608.         } else {
  609.             keypad[0][5].label = "Deg";
  610.         keypad[0][5].invlabel = "Deg";
  611.         }
  612.         muiLoadButton(keypad[0][5].b, keypad[0][5].label);
  613.         degreemode = 1 - degreemode;
  614.         loadbuttons(invmode);
  615.         break;
  616.     case Invkey:
  617.         if (invmode) {
  618.         invmode = 0;
  619.         loadbuttons(0);
  620.         } else {
  621.         invmode = 2;
  622.         loadbuttons(1);
  623.         }
  624.         break;
  625.     case Progkey:
  626.         if (savingprog == 0) {
  627.         proglen = 0;
  628.         }
  629.         savingprog = 1 - savingprog;
  630.         break;
  631.     case Runkey:
  632.         if (savingprog) break;
  633.         for (i = 0; i < proglen; i++)
  634.             interpclick(program[i]);
  635.         break;
  636.     case Storekey:
  637.         unop(Storekey); break;
  638.     case Recallkey:
  639.         unop(Recallkey); break;
  640.     case Oneoverkey:
  641.         unop(Oneoverkey); break;
  642.     case Sinkey:
  643.         unop(Sinkey); break;
  644.     case Coskey:
  645.         unop(Coskey); break;
  646.     case Tankey:
  647.         unop(Tankey); break;
  648.     case Expkey:
  649.         unop(Expkey); break;
  650.     case Tentoxkey:
  651.         unop(Tentoxkey); break;
  652.     case Intkey:
  653.         unop(Intkey); break;
  654.     case Andkey:
  655.         binop('&'); break;
  656.     case Orkey:
  657.         binop('|'); break;
  658.     case Notkey:
  659.         unop(Notkey); break;
  660.     case Base10key:
  661.         if (enablepush == 0) doenter();
  662.         base = 10;
  663.         for (i = Displaylines-1; i <= CSP; i++)
  664.             formatentry(i);
  665.         glutPostRedisplay();
  666.         break;
  667.     case Base16key:
  668.         if (enablepush == 0) doenter();
  669.         base = 16;
  670.         for (i = Displaylines-1; i <= CSP; i++)
  671.             formatentry(i);
  672.         glutPostRedisplay();
  673.         break;
  674.     case Sqrtkey:
  675.         unop(Sqrtkey); break;
  676.     }
  677.     if (invmode == 1) {
  678.     loadbuttons(0);
  679.     }
  680.     if (invmode > 0) invmode--;
  681. }
  682.  
  683. void showhelp(void)
  684. {
  685. printf("\n\n------------------------------------------\n\n");
  686. printf("Calc is a Reverse-Polish-Notation (RPN) calculator.  You\n");
  687. printf("must enter the operands first, then the operation.  For\n");
  688. printf("example, to add 3 and 4, press [3] [Enter] [4] [+].  If\n");
  689. printf("the operation is unary, like sine, it operates on the bottom\n");
  690. printf("element of the display.  To take the sine of .54, do:\n");
  691. printf("\n");
  692. printf("[.] [5] [4] [Sin].\n");
  693. printf("\n");
  694. printf("The last 6 entries of the stack are visible, and you can\n");
  695. printf("scroll to see the rest.  All operations are performed on\n");
  696. printf("the element(s) at the bottom of the stack.  The bottom\n");
  697. printf("element is called 'x' and the next element up is called 'y'.\n");
  698. printf("\n");
  699. printf("The [+/-] key changes the sign of x.  To find the cosine of\n");
  700. printf("-.22, do:\n");
  701. printf("\n");
  702. printf("[.] [2] [2] [+/-] [Cos].\n");
  703. printf("\n");
  704. printf("The [Inv] key changes the operation of some of the other keys\n");
  705. printf("so they perform the inverse operation.  It is only active for\n");
  706. printf("one keystroke.  Press [Inv] again to cancel the operation.\n");
  707. printf("\n");
  708. printf("[Sto] and [Rcl] stores and recalls a single value.\n");
  709. printf("\n");
  710. printf("[Dup2] duplicates the bottom 2 items on the stack.\n");
  711. printf("\n");
  712. printf("[Roll] rolls all the stack elements down one, and puts the\n");
  713. printf("bottom element on the top.\n");
  714. printf("\n");
  715. printf("[Exch] swaps the bottom two elements.\n");
  716. printf("\n");
  717. printf("[Int] gives the integer part.\n");
  718. printf("\n");
  719. printf("[Inv] [Frac] gives the fractional part.\n");
  720. printf("\n");
  721. printf("[Clr] clears the bottom element to zero.  Use this when you\n");
  722. printf("get some kind of error\n");
  723. printf("\n");
  724. printf("[B10] and [B16] put you in base 10 or base 16 mode.  Numbers\n");
  725. printf("with fractional parts are always displayed in base 10.  In\n");
  726. printf("base 16 mode, the keys [a] through [f] are used for numeric\n");
  727. printf("entry.  They do nothing, otherwise.\n");
  728. printf("\n");
  729. printf("[And], [Or] and [Not] are logical operations on 32 bit\n");
  730. printf("integers.  If there's a fractional part, they don't do\n");
  731. printf("anything.\n");
  732. printf("\n");
  733. printf("To remember a sequence of keystrokes, press [Prog], then the\n");
  734. printf("sequence of keystrokes, and then [Prog] again.  For example,\n");
  735. printf("if you want to calculate x^2 + y^2 repeatedly, where x and y\n");
  736. printf("are the two bottom entries of the stack, do this:\n");
  737. printf("\n");
  738. printf("[Prog] [Inv] [x^2] [Exch] [Inv] [x^2] [+] [Prog].\n");
  739. printf("\n");
  740. printf("Then, to calculate 5^2+7^2, do this:\n");
  741. printf("\n");
  742. printf("[5] [Enter] [7] [Run].\n");
  743. printf("\n");
  744. printf("The following keys from the computer keyboard are understood\n");
  745. printf("by calc:\n");
  746. printf("\n");
  747. printf("[0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [.],\n");
  748. printf("[Enter], [+], [-], [*], [/], [a], [b], [c], [d], [e], [f].\n");
  749. printf("\n");
  750. printf("The [Deg]/[Rad] key shows the current angle mode.  Press\n");
  751. printf("it to get the other angle mode.\n");
  752. printf("\n------------------------------------------\n\n");
  753. }
  754.